package sequence

import (
	
	
	

	
)

const (
	SequenceDiagramKeyword = "sequenceDiagram"
	SolidArrowSyntax       = "->>"
	DottedArrowSyntax      = "-->>"
)

var (
	// participantRegex matches participant declarations: participant [ID] [as Label]
	participantRegex = regexp.MustCompile(`^\s*participant\s+(?:"([^"]+)"|(\S+))(?:\s+as\s+(.+))?$`)

	// messageRegex matches messages: [From]->>[To]: [Label]
	messageRegex = regexp.MustCompile(`^\s*(?:"([^"]+)"|([^\s\->]+))\s*(-->>|->>)\s*(?:"([^"]+)"|([^\s\->]+))\s*:\s*(.*)$`)

	// autonumberRegex matches the autonumber directive
	autonumberRegex = regexp.MustCompile(`^\s*autonumber\s*$`)
)

// SequenceDiagram represents a parsed sequence diagram.
type SequenceDiagram struct {
	Participants []*Participant
	Messages     []*Message
	Autonumber   bool
}

type Participant struct {
	ID    string
	Label string
	Index int
}

type Message struct {
	From      *Participant
	To        *Participant
	Label     string
	ArrowType ArrowType
	Number    int // Message number when autonumber is enabled (0 means no number)
}

type ArrowType int

const (
	SolidArrow ArrowType = iota
	DottedArrow
)

func ( ArrowType) () string {
	switch  {
	case SolidArrow:
		return "solid"
	case DottedArrow:
		return "dotted"
	default:
		return fmt.Sprintf("ArrowType(%d)", )
	}
}

func ( string) bool {
	 := strings.Split(, "\n")
	for ,  := range  {
		 := strings.TrimSpace()
		if  == "" || strings.HasPrefix(, "%%") {
			continue
		}
		return strings.HasPrefix(, SequenceDiagramKeyword)
	}
	return false
}

func ( string) (*SequenceDiagram, error) {
	 = strings.TrimSpace()
	if  == "" {
		return nil, fmt.Errorf("empty input")
	}

	 := diagram.SplitLines()
	 := diagram.RemoveComments()
	if len() == 0 {
		return nil, fmt.Errorf("no content found")
	}

	if !strings.HasPrefix(strings.TrimSpace([0]), SequenceDiagramKeyword) {
		return nil, fmt.Errorf("expected %q keyword", SequenceDiagramKeyword)
	}
	 = [1:]

	 := &SequenceDiagram{
		Participants: []*Participant{},
		Messages:     []*Message{},
		Autonumber:   false,
	}
	 := make(map[string]*Participant)

	for ,  := range  {
		 := strings.TrimSpace()
		if  == "" {
			continue
		}

		// Check for autonumber directive
		if autonumberRegex.MatchString() {
			.Autonumber = true
			continue
		}

		if ,  := .parseParticipant(, );  != nil {
			return nil, fmt.Errorf("line %d: %w", +2, )
		} else if  {
			continue
		}

		if ,  := .parseMessage(, );  != nil {
			return nil, fmt.Errorf("line %d: %w", +2, )
		} else if  {
			continue
		}

		return nil, fmt.Errorf("line %d: invalid syntax: %q", +2, )
	}

	if len(.Participants) == 0 {
		return nil, fmt.Errorf("no participants found")
	}

	return , nil
}

func ( *SequenceDiagram) ( string,  map[string]*Participant) (bool, error) {
	 := participantRegex.FindStringSubmatch()
	if  == nil {
		return false, nil
	}

	 := [2]
	if [1] != "" {
		 = [1]
	}
	 := [3]
	if  == "" {
		 = 
	}
	 = strings.Trim(, `"`)

	if ,  := [];  {
		return true, fmt.Errorf("duplicate participant %q", )
	}

	 := &Participant{
		ID:    ,
		Label: ,
		Index: len(.Participants),
	}
	.Participants = append(.Participants, )
	[] = 
	return true, nil
}

func ( *SequenceDiagram) ( string,  map[string]*Participant) (bool, error) {
	 := messageRegex.FindStringSubmatch()
	if  == nil {
		return false, nil
	}

	 := [2]
	if [1] != "" {
		 = [1]
	}

	 := [3]

	 := [5]
	if [4] != "" {
		 = [4]
	}

	 := strings.TrimSpace([6])

	 := .getParticipant(, )
	 := .getParticipant(, )

	 := DottedArrow
	if  == SolidArrowSyntax {
		 = SolidArrow
	}

	 := 0
	if .Autonumber {
		 = len(.Messages) + 1
	}

	 := &Message{
		From:      ,
		To:        ,
		Label:     ,
		ArrowType: ,
		Number:    ,
	}
	.Messages = append(.Messages, )
	return true, nil
}

func ( *SequenceDiagram) ( string,  map[string]*Participant) *Participant {
	if ,  := [];  {
		return 
	}

	 := &Participant{
		ID:    ,
		Label: ,
		Index: len(.Participants),
	}
	.Participants = append(.Participants, )
	[] = 
	return 
}